package quartz.service;

import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Service;
import quartz.entity.JobEntity;
import quartz.job.JobExecutor;

@Slf4j
@Service
public class QuartzHelper {
    @Autowired
    private SchedulerFactoryBean schedulerFactoryBean;

    public void addJob(JobEntity jobEntity) {
        JobDetail jobDetail = JobBuilder
                .newJob(JobExecutor.class)
                .withIdentity(jobEntity.getJobName(), jobEntity.getJobGroup())
                .setJobData(buildJobDataMap(jobEntity))
                .build();
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(jobEntity.getCron());
        CronTrigger cronTrigger = TriggerBuilder
                .newTrigger()
                .withIdentity(jobEntity.getTriggerName(), jobEntity.getTriggerGroup())
                .withSchedule(scheduleBuilder)
                .build();
        try {
            schedulerFactoryBean.getScheduler().scheduleJob(jobDetail, cronTrigger);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    public void deleteJob(JobEntity jobEntity) {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        try {
            scheduler.pauseTrigger(new TriggerKey(jobEntity.getTriggerName(), jobEntity.getTriggerGroup()));
            scheduler.unscheduleJob(new TriggerKey(jobEntity.getTriggerName(), jobEntity.getTriggerGroup()));
            scheduler.deleteJob(new JobKey(jobEntity.getJobName(), jobEntity.getJobGroup()));
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    public void updateJob(JobEntity jobEntity) {
        deleteJob(jobEntity);
        addJob(jobEntity);
        if (Boolean.FALSE.equals(jobEntity.getIsActive())) {
            pauseJob(jobEntity);
        }
    }

    public void pauseJob(JobEntity jobEntity) {
        try {
            schedulerFactoryBean.getScheduler().pauseJob(new JobKey(jobEntity.getJobName(), jobEntity.getJobGroup()));
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    public void resumeJob(JobEntity jobEntity) {
        try {
            schedulerFactoryBean.getScheduler().resumeJob(new JobKey(jobEntity.getJobName(), jobEntity.getJobGroup()));
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    public void executeJob(JobEntity jobEntity) {
        try {
            schedulerFactoryBean.getScheduler().triggerJob(
                    new JobKey(jobEntity.getJobName(), jobEntity.getJobGroup()),
                    buildJobDataMap(jobEntity)
            );
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    private JobDataMap buildJobDataMap(JobEntity jobEntity) {
        JobDataMap jobDataMap = new JobDataMap();
        jobDataMap.put("classPath", jobEntity.getClassPath());
        jobDataMap.put("targetMethod", jobEntity.getTargetMethod());
        jobDataMap.put("cron", jobEntity.getCron());
        jobDataMap.put("description", jobEntity.getDescription());
        jobDataMap.put("isActive", jobEntity.getIsActive());
        return jobDataMap;
    }
}
